<!--

SIMPLE LANGUAGE LEXICAL GRAMMAR

Language is case sensitive
Identifier: Must start with a letter or _ and can only contain letters, digits, and _ characters
Number: Digits (integers only)
Keywords: function, return, var
Operators: = == != + - * /
Punctuation: { } ( ) , ;
Single-line Comment:  // Comment text
Multi-line Comment:  /* Comment text */

=====================================================================

SIMPLE LANGUAGE SEMANTIC GRAMMAR (EBNF)

CompilationUnit:
	FunctionDeclarationList?

FunctionDeclarationList:
	FunctionDeclaration
	FunctionDeclarationList FunctionDeclaration

FunctionDeclaration:
	"function" "identifier" "(" FunctionParameterList? ")" Block

FunctionParameterList:
	"identifier"
	FunctionParameterList "," "identifier"

StatementList:
	Statement
	StatementList Statement

Statement:
	Block
	EmptyStatement
	VariableDeclarationStatement
	AssignmentStatement
	ReturnStatement
	
Block:
	"{" StatementList "}"

EmptyStatement:
	";"
	
VariableDeclarationStatement:
	"var" "identifier" ";"

AssignmentStatement:
	"identifier" "=" Expression ";"
	
ReturnStatement:
	"return" Expression ";"
	
Expression: 
	EqualityExpression

EqualityExpression:
	AdditiveExpression
	AdditiveExpression "==" EqualityExpression
	AdditiveExpression "!=" EqualityExpression
	
AdditiveExpression:
	MultiplicativeExpression
	MultiplicativeExpression "+" AdditiveExpression
	MultiplicativeExpression "-" AdditiveExpression

MultiplicativeExpression:
	PrimaryExpression
	PrimaryExpression "*" MultiplicativeExpression
	PrimaryExpression "/" MultiplicativeExpression
	
PrimaryExpression:
	NumberExpression
	SimpleName
	FunctionAccessExpression
	ParenthesizedExpression

NumberExpression:
	"number"

SimpleName:
	"identifier"

FunctionAccessExpression:
	"identifier" "(" FunctionArgumentList? ")"

FunctionArgumentList:
	FunctionArgument
	FunctionArgumentList "," FunctionArgument

FunctionArgument:
	Expression

ParenthesizedExpression:
	"(" Expression ")"

=====================================================================

GRAMMAR PRODUCTION SYNTAX
'abc' - Terminal (token) with name "abc"
"abc" - Non-terminal with name "abc"
  |   - Alternation
 ( )  - Grouping
 [ ]  - Optional
 { }  - Iteration (zero or more)
<% %> - User code
<@ @> - Parameter code
<? ?> - Conditional code (can be used after a "[", "{", or "|")
<- -> - Failure match code
<+ +> - Successful match code

VALID IN CUSTOM CODE ONLY
IsNonTerminal("abc") - Returns a boolean as to whether the LookAheadToken can start the non-terminal "abc" 
IsNonTerminal("abc", "this.PeekToken") - Returns a boolean as to whether the specified token can start the non-terminal "abc" 

-->
<Grammar 
	LanguageName="Simple" 
	TypeName="SimpleSemanticParser"
	Namespace="ActiproSoftware.SyntaxEditor.Addons.Simple"
	RootNonTerminal="CompilationUnit"
	LexicalStateIDTypeName="SimpleLexicalStateID"
	TokenIDTypeName="SimpleTokenID"
	OutputLanguage="C#">
	<ImportedNamespaces>
		<ImportedNamespace>System.Collections</ImportedNamespace>
		<ImportedNamespace>System.Diagnostics</ImportedNamespace>
		<ImportedNamespace>System.Text</ImportedNamespace>
	</ImportedNamespaces>
	<LexicalStates>
		<LexicalState>Default</LexicalState>
	</LexicalStates>
	<Tokens>
		<!-- NOTE: Any changes here need to be made to SimpleSyntaxLanguage.GetTokenString -->
		<Token>Invalid</Token>
		<Token>DocumentEnd</Token>
		<Token>LanguageTransitionStart</Token>
		<Token>LanguageTransitionEnd</Token>

		<Token IsSignificant="false">Whitespace</Token>
		<Token IsSignificant="false">LineTerminator</Token>

		<Token IsSignificant="false">SingleLineComment</Token>
		<Token IsSignificant="false">MultiLineComment</Token>
		
		<Token>Number</Token>
		<Token>Identifier</Token>

		<Token IsSignificant="false">KeywordStart</Token>
		<Token>Function</Token>
		<Token>Var</Token>
		<Token>Return</Token>
		<Token IsSignificant="false">KeywordEnd</Token>

		<Token IsSignificant="false">OperatorOrPunctuatorStart</Token>
		<Token>OpenCurlyBrace</Token>
		<Token>CloseCurlyBrace</Token>
		<Token>OpenParenthesis</Token>
		<Token>CloseParenthesis</Token>
		<Token>Comma</Token>
		<Token>SemiColon</Token>
		<Token>Addition</Token>
		<Token>Subtraction</Token>
		<Token>Multiplication</Token>
		<Token>Division</Token>
		<Token>Assignment</Token>
		<Token>Equality</Token>
		<Token>Inequality</Token>
		<Token IsSignificant="false">OperatorOrPunctuatorEnd</Token>

		<Token>MaxTokenID</Token>		
	</Tokens>
	<Ast Generate="true" VisitorPatternSupported="true" Namespace="ActiproSoftware.SyntaxEditor.Addons.Simple.Ast" NodeTypeEnumTypeName="SimpleNodeType">
		<AstNodes>
			<AstNode> 
				<!-- NOTE: No Name attribute on an AstNode element will target the AstNode base class for the language...
							No attributes or child elements other than the AstNodeDeclarations element are currently recognized for the base node.
					-->
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets the image index that is applicable for displaying this node in a user interface control.
					/// </summary>
					/// <value>The image index that is applicable for displaying this node in a user interface control.</value>
					public override int ImageIndex {
						get {
							return (int)ActiproSoftware.Products.SyntaxEditor.IconResource.Keyword;
						}
					}
									
				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="AssignmentStatement" Inherits="Statement" Description="An assignment statement.">
				<AstNodeProperty PropertyType="AstNode" Name="VariableName" Type="Identifier" Description="The variable name." />
				<AstNodeProperty PropertyType="AstNode" Name="Expression" Type="Expression" Description="The expression." />
				<AstNodeDeclarations Type="Constructor"><![CDATA[	

					/// <summary>
					/// Initializes a new instance of the <c>AssignmentStatement</c> class. 
					/// </summary>
					/// <param name="variableName">The variable name.</param>
					/// <param name="textRange">The <see cref="TextRange"/> of the AST node.</param>
					public AssignmentStatement(Identifier variableName, Expression expression, TextRange textRange) : this(textRange) {
						// Initialize parameters
						this.VariableName = variableName;
						this.Expression = expression;
					}
						
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "Assignment of " + this.VariableName.Text;
						}
					}
									
				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="BinaryExpression" Inherits="Expression" Description="A binary expression." ImageIndex="(System.Int32)ActiproSoftware.Products.SyntaxEditor.IconResource.Operator">
				<AstNodeProperty PropertyType="AstNode" Name="LeftExpression" Type="Expression" Description="The left expression affected by the binary operator." />
				<AstNodeProperty PropertyType="AstNode" Name="RightExpression" Type="Expression" Description="The right expression affected by the binary operator." />
				<AstNodeProperty PropertyType="Simple" Name="OperatorType" Type="OperatorType" Description="An operator type indicating the binary operator type." />
				<AstNodeDeclarations Type="Constructor"><![CDATA[	

					/// <summary>
					/// Initializes a new instance of the <c>BinaryExpression</c> class. 
					/// </summary>
					/// <param name="operatorType">An <see cref="OperatorType"/> indicating the binary operator type.</param>
					/// <param name="leftExpression">The left <see cref="Expression"/> affected by the unary operator.</param>
					/// <param name="rightExpression">The right <see cref="Expression"/> affected by the unary operator.</param>
					/// <param name="textRange">The <see cref="TextRange"/> of the expression.</param>
					public BinaryExpression(OperatorType operatorType, Expression leftExpression, Expression rightExpression, TextRange textRange) : this(textRange) {
						// Initialize parameters
						this.operatorType		= operatorType;
						this.LeftExpression		= leftExpression;
						this.RightExpression	= rightExpression;
					}
						
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "Binary Expression " + this.OperatorType;
						}
					}
				
				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="BlockStatement" Inherits="Statement" Description="A block of statements." ImageIndex="(System.Int32)ActiproSoftware.Products.SyntaxEditor.IconResource.Namespace">
				<AstNodeProperty PropertyType="AstNodeList" Name="Statements" Description="The collection of statements." />
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "Block";
						}
					}

				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="CompilationUnit" Implements="ICompilationUnit, ISemanticParseData" Description="A Simple language compilation unit.">
				<AstNodeProperty PropertyType="AstNodeList" Name="Functions" Description="The collection of functions." />
				<AstNodeProperty PropertyType="Simple" Name="SourceKey" Type="System.String" Description="The string-based key that identifies the source of the code, which typically is a filename." />
				<AstNodeDeclarations Type="Field"><![CDATA[	
					private bool						hasLanguageTransitions;
					private ArrayList					syntaxErrors;
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Returns whether an <see cref="CollapsibleNodeOutliningParser"/> should visit the child nodes of the specified <see cref="IAstNode"/>
					/// to look for collapsible nodes.
					/// </summary>
					/// <param name="node">The <see cref="IAstNode"/> to examine.</param>
					/// <returns>
					/// <c>true</c> if the child nodes should be visited; otherwise, <c>false</c>.
					/// </returns>
					bool ICompilationUnit.ShouldVisitChildNodesForOutlining(IAstNode node) {
						return true;
					}
					
					/// <summary>
					/// Adds any extra <see cref="CollapsibleNodeOutliningParserData"/> nodes to the <see cref="CollapsibleNodeOutliningParser"/>,
					/// such as for comments that should be marked as collapsible.
					/// </summary>
					/// <param name="outliningParser">The <see cref="CollapsibleNodeOutliningParser"/> to update.</param>
					void ICompilationUnit.UpdateOutliningParser(CollapsibleNodeOutliningParser outliningParser) {
					}
							
					/// <summary>
					/// Gets whether the compilation unit contains errors.
					/// </summary>
					/// <value>
					/// <c>true</c> if the compilation unit contains errors.
					/// </value>
					public bool HasErrors { 
						get {
							return ((syntaxErrors != null) && (syntaxErrors.Count > 0));
						}
					}
					
					/// <summary>
					/// Gets or sets whether the compilation unit contains any language transitions.
					/// </summary>
					/// <value>
					/// <c>true</c> if the compilation unit contains any language transitions; otherwise, <c>false</c>.
					/// </value>
					public bool HasLanguageTransitions { 
						get {
							return hasLanguageTransitions;
						}
						set {
							hasLanguageTransitions = value;
						}
					}

					/// <summary>
					/// Gets whether the AST node is a language root node.
					/// </summary>
					/// <value>
					/// <c>true</c> if the AST node is a language root node; otherwise, <c>false</c>.
					/// </value>
					/// <remarks>
					/// When in a scenario where AST node trees from multiple languages have been merged together,
					/// it is useful to identify where child language AST node trees begin within their parents.
					/// </remarks>
					public override bool IsLanguageRoot {
						get {
							return true;
						}
					}
					
					/// <summary>
					/// Gets the collection of syntax errors that were found in the compilation unit.
					/// </summary>
					/// <value>The collection of syntax errors that were found in the compilation unit.</value>
					public IList SyntaxErrors {
						get {
							if (syntaxErrors == null)
								syntaxErrors = new ArrayList();

							return syntaxErrors;
						}
					}
					
				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="EmptyStatement" Inherits="Statement" Description="An empty statement." />
			<AstNode Name="Expression" IsAbstract="true" Description="The base class for an expression." />
			<AstNode Name="FunctionAccessExpression" Inherits="Expression" Description="A function access expression.">
				<AstNodeProperty PropertyType="AstNode" Name="FunctionName" Type="Identifier" Description="The function name." />
				<AstNodeProperty PropertyType="AstNodeList" Name="Parameters" Description="The collection of expression parameters." />
				<AstNodeDeclarations Type="Constructor"><![CDATA[	

					/// <summary>
					/// Initializes a new instance of the <c>FunctionAccessExpression</c> class. 
					/// </summary>
					/// <param name="functionName">The function name.</param>
					public FunctionAccessExpression(Identifier functionName) {
						// Initialize parameters
						this.FunctionName = functionName;
					}
					
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "Call to Function " + this.FunctionName.Text;
						}
					}

				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="FunctionDeclaration" Implements="ICollapsibleNode" Description="A function declaration." ImageIndex="(System.Int32)ActiproSoftware.Products.SyntaxEditor.IconResource.PublicMethod">
				<AstNodeProperty PropertyType="AstNode" Name="BlockStatement" Type="BlockStatement" Description="The block statement." />
				<AstNodeProperty PropertyType="AstNode" Name="Name" Type="Identifier" Description="The name." />
				<AstNodeProperty PropertyType="AstNodeList" Name="Parameters" Description="The collection of parameters." />
				<AstNodeDeclarations Type="Field"><![CDATA[	
					private int					blockEndOffset						= -1;
					private int					blockStartOffset					= -1;
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets the offset at which the outlining node ends.
					/// </summary>
					/// <value>The offset at which the outlining node ends.</value>
					int ICollapsibleNode.EndOffset { 
						get {
							return blockEndOffset;
						}
					}

					/// <summary>
					/// Gets whether the node is collapsible.
					/// </summary>
					/// <value>
					/// <c>true</c> if the node is collapsible; otherwise, <c>false</c>.
					/// </value>
					bool ICollapsibleNode.IsCollapsible { 
						get {
							return (blockStartOffset != -1) && ((blockStartOffset < blockEndOffset) || (blockEndOffset == -1));
						}
					}

					/// <summary>
					/// Gets the offset at which the outlining node starts.
					/// </summary>
					/// <value>The offset at which the outlining node starts.</value>
					int ICollapsibleNode.StartOffset { 
						get {
							return blockStartOffset;
						}
					}
					
					/// <summary>
					/// Gets whether the outlining indicator should be visible for the node.
					/// </summary>
					/// <value>
					/// <c>true</c> if the outlining indicator should be visible for the node; otherwise, <c>false</c>.
					/// </value>
					bool IOutliningNodeParseData.IndicatorVisible { 
						get {
							return true;
						}
					}

					/// <summary>
					/// Gets whether the outlining node is for a language transition.
					/// </summary>
					/// <value>
					/// <c>true</c> if the outlining node is for a language transition; otherwise, <c>false</c>.
					/// </value>
					bool IOutliningNodeParseData.IsLanguageTransition { 
						get {
							return false;
						}
					}
								
					/// <summary>
					/// Gets or sets the end character offset of the end block delimiter in the original source code that generated the AST node.
					/// </summary>
					/// <value>The end character offset of the end block delimiter in the original source code that generated the AST node.</value>
					/// <remarks>
					/// This value may be <c>-1</c> if there is no source code information for the end character offset.
					/// </remarks>
					public int BlockEndOffset {
						get {
							return blockEndOffset;
						}
						set {
							blockEndOffset = value;
						}
					}
					
					/// <summary>
					/// Gets or sets the start character offset of the start block delimiter in the original source code that generated the AST node.
					/// </summary>
					/// <value>The start character offset of the start block delimiter in the original source code that generated the AST node.</value>
					/// <remarks>
					/// This value may be <c>-1</c> if there is no source code information for the start character offset.
					/// </remarks>
					public int BlockStartOffset {
						get {
							return blockStartOffset;
						}
						set {
							blockStartOffset = value;
						}
					}
					
					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							StringBuilder text = new StringBuilder();
							text.Append("Function ");
							text.Append(this.Name.Text);
							text.Append("(");
							IAstNodeList parameters = this.Parameters;
							for (int index = 0; index < parameters.Count; index++) {
								if (index > 0)
									text.Append(", " );
								text.Append(((Identifier)parameters[index]).Text);
							}
							text.Append(")");
							return text.ToString();
						}
					}

					/// <summary>
					/// Gets the character offset at which to navigate when the editor's caret should jump to the text representation of the AST node.
					/// </summary>
					/// <value>The character offset at which to navigate when the editor's caret should jump to the text representation of the AST node.</value>
					public override int NavigationOffset {
						get {
							Identifier name = this.Name;
							if ((name != null) && (name.HasStartOffset))
								return name.NavigationOffset;
							else
								return base.NavigationOffset;
						}
					}
					
				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="Identifier" Description="An identifier.">
				<AstNodeProperty PropertyType="Simple" Name="Text" Type="System.String" Description="The text of the qualified identifier." />
				<AstNodeDeclarations Type="Constructor"><![CDATA[	

					/// <summary>
					/// Initializes a new instance of the <c>Identifier</c> class. 
					/// </summary>
					/// <param name="text">The text of the qualified identifier.</param>
					/// <param name="textRange">The <see cref="TextRange"/> of the AST node.</param>
					public Identifier(string text, TextRange textRange) : this(textRange) {
						// Initialize parameters
						this.text = text;
					}

				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "Identifier " + text;
						}
					}

				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="NumberExpression" Inherits="Expression" Description="A number expression.">
				<AstNodeProperty PropertyType="Simple" Name="Number" Type="System.Int32" Description="The number." />
				<AstNodeDeclarations Type="Constructor"><![CDATA[	

					/// <summary>
					/// Initializes a new instance of the <c>NumberExpression</c> class. 
					/// </summary>
					/// <param name="number">The number.</param>
					/// <param name="textRange">The <see cref="TextRange"/> of the AST node.</param>
					public NumberExpression(int number, TextRange textRange) : this(textRange) {
						// Initialize parameters
						this.number = number;
					}
					
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "Number " + this.Number;
						}
					}

				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="ParenthesizedExpression" Inherits="Expression" Description="A parenthesized expression.">
				<AstNodeProperty PropertyType="AstNode" Name="Expression" Type="Expression" Description="The expression contained by the parenthesis." />
				<AstNodeDeclarations Type="Constructor"><![CDATA[	

					/// <summary>
					/// Initializes a new instance of the <c>ParenthesizedExpression</c> class. 
					/// </summary>
					/// <param name="expression">The <see cref="Expression"/> affected by the checked modifier.</param>
					/// <param name="textRange">The <see cref="TextRange"/> of the AST node.</param>
					public ParenthesizedExpression(Expression expression, TextRange textRange) : this(textRange) {
						// Initialize parameters
						this.Expression = expression;
					}
					
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "( Parenthesized Expression )";
						}
					}

				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="ReturnStatement" Inherits="Statement" Description="A return statement.">
				<AstNodeProperty PropertyType="AstNode" Name="Expression" Type="Expression" Description="The expression to be returned." />
				<AstNodeDeclarations Type="Constructor"><![CDATA[	

					/// <summary>
					/// Initializes a new instance of the <c>ReturnStatement</c> class. 
					/// </summary>
					/// <param name="expression">The <see cref="Expression"/>.</param>
					/// <param name="textRange">The <see cref="TextRange"/> of the AST node.</param>
					public ReturnStatement(Expression expression, TextRange textRange) : this(textRange) {
						// Initialize parameters
						this.Expression = expression;
					}
					
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "Return";
						}
					}

				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="SimpleName" Inherits="Expression" Description="A simple name.">
				<AstNodeProperty PropertyType="Simple" Name="Name" Type="System.String" Description="The name." />
				<AstNodeDeclarations Type="Constructor"><![CDATA[	

					/// <summary>
					/// Initializes a new instance of the <c>SimpleName</c> class. 
					/// </summary>
					/// <param name="name">The name.</param>
					/// <param name="textRange">The <see cref="TextRange"/> of the AST node.</param>
					public SimpleName(string name, TextRange textRange) : base(textRange) {
						// Initialize parameters
						this.Name = name;
					}
					
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "Simple Name " + this.Name;
						}
					}

				]]></AstNodeDeclarations>
			</AstNode>
			<AstNode Name="Statement" IsAbstract="true" Description="The base class for a statement." />
			<AstNode Name="VariableDeclarationStatement" Inherits="Statement" Description="A variable declaration statement.">
				<AstNodeProperty PropertyType="AstNode" Name="VariableName" Type="Identifier" Description="The variable name." />
				<AstNodeDeclarations Type="Constructor"><![CDATA[	

					/// <summary>
					/// Initializes a new instance of the <c>VariableDeclarationStatement</c> class. 
					/// </summary>
					/// <param name="variableName">The variable name.</param>
					/// <param name="textRange">The <see cref="TextRange"/> of the AST node.</param>
					public VariableDeclarationStatement(Identifier variableName, TextRange textRange) : this(textRange) {
						// Initialize parameters
						this.VariableName = variableName;
					}
					
				]]></AstNodeDeclarations>
				<AstNodeDeclarations><![CDATA[	

					/// <summary>
					/// Gets text representing the node that can be used for display, such as in a document outline.
					/// </summary>
					/// <value>Text representing the node that can be used for display, such as in a document outline.</value>
					public override string DisplayText {
						get {
							return "Variable Declaration of " + this.VariableName.Text;
						}
					}

				]]></AstNodeDeclarations>
			</AstNode>
		</AstNodes>
	</Ast>
	<Declarations><![CDATA[
		
		private CompilationUnit	compilationUnit;
		private System.Int32	curlyBraceLevel;

		/// <summary>
		/// Initializes a new instance of the <c>SimpleSemanticParser</c> class.
		/// </summary>
		/// <param name="lexicalParser">The <see cref="ActiproSoftware.SyntaxEditor.ParserGenerator.IRecursiveDescentLexicalParser"/> to use for lexical parsing.</param>
		public SimpleSemanticParser(ActiproSoftware.SyntaxEditor.ParserGenerator.IRecursiveDescentLexicalParser lexicalParser) : base(lexicalParser) {}
	
		/// <summary>
		/// Advances to the next <see cref="IToken"/>.
		/// </summary>
		/// <returns>
		/// The <see cref="IToken"/> that was read.
		/// </returns>
		protected override IToken AdvanceToNext() {
			IToken token = base.AdvanceToNext();
			if (!this.TokenIsLanguageChange(token)) {
				switch (token.ID) {
					case SimpleTokenID.OpenCurlyBrace:
						curlyBraceLevel++;
						break;
					case SimpleTokenID.CloseCurlyBrace:
						curlyBraceLevel--;
						break;
				}
			}
			return token;
		}

		/// <summary>
		/// Advances to (or past) the next matching close curly brace.
		/// </summary>
		/// <param name="movePast">Whether to move past the close curly brace.</param>
		/// <param name="openCurlyBraceLevel">The level of the open curly brace.</param>	
		private void AdvanceToNextCloseCurlyBrace(System.Int32 openCurlyBraceLevel, System.Boolean movePast) {
			while (!this.IsAtEnd) {
				this.AdvanceToNext(SimpleTokenID.OpenCurlyBrace, SimpleTokenID.CloseCurlyBrace); 
				if ((this.TokenIs(this.LookAheadToken, SimpleTokenID.CloseCurlyBrace)) && (curlyBraceLevel <= openCurlyBraceLevel + 1))
					break;
				this.AdvanceToNext();
			}			
			if ((movePast) && (this.TokenIs(this.LookAheadToken, SimpleTokenID.CloseCurlyBrace)))
				this.AdvanceToNext();
		}
	
		/// <summary>
		/// Gets the <see cref="CompilationUnit"/> that was parsed.
		/// </summary>
		/// <value>The <see cref="CompilationUnit"/> that was parsed.</value>
		public CompilationUnit CompilationUnit {
			get {
				return compilationUnit;
			}
		}
	
		/// <summary>
		/// Reports a syntax error.
		/// </summary>
		/// <param name="textRange">The <see cref="TextRange"/> of the error.</param>
		/// <param name="message">The error message.</param>
		protected override void ReportSyntaxError(TextRange textRange, System.String message) {
			// Don't allow multiple errors at the same offset
			if ((compilationUnit.SyntaxErrors.Count > 0) && (((SyntaxError)compilationUnit.SyntaxErrors[compilationUnit.SyntaxErrors.Count - 1]).TextRange.StartOffset == textRange.StartOffset))
				return;
			
			compilationUnit.SyntaxErrors.Add(new SyntaxError(textRange, message));
		}
		
	]]></Declarations>
	<NonTerminals>
	
		<NonTerminal Key="CompilationUnit">
			<Production><![CDATA[
				<% 
					curlyBraceLevel = 0;
					compilationUnit = new CompilationUnit();
					compilationUnit.StartOffset = this.LookAheadToken.StartOffset;
					System.Boolean errorReported = false;
					while (!this.IsAtEnd) {
						if (IsNonTerminal("FunctionDeclaration")) {
							errorReported = false;
					%>
							{ "FunctionDeclaration<- ->" }
					<% 
						}
						else {
							// Error recovery:  Advance to the next token since nothing was matched
							if (!errorReported) {
								this.ReportSyntaxError("Function declaration expected.");
								errorReported = true;
							}
							this.AdvanceToNext();
						}
					}
					compilationUnit.EndOffset = this.LookAheadToken.EndOffset;
				%>
			]]></Production>
		</NonTerminal>
		<NonTerminal Key="FunctionDeclaration">
			<Production><![CDATA[
				<%
					FunctionDeclaration functionDeclaration = new FunctionDeclaration();
					functionDeclaration.StartOffset = this.LookAheadToken.StartOffset;
					Identifier name;
					AstNodeList parameterList = null;
					Statement blockStatement;
				%>
				'Function'
				"Identifier<@ out name @>"
				'OpenParenthesis'
				<%
					functionDeclaration.Name = name;
					compilationUnit.Functions.Add(functionDeclaration);
				%>
				[ "FunctionParameterList<@ out parameterList @>" ]
				'CloseParenthesis<- ->'
				<%
					if (parameterList != null)
						functionDeclaration.Parameters.AddRange(parameterList.ToArray());				
					functionDeclaration.BlockStartOffset = this.LookAheadToken.StartOffset;
				%>
				"Block<@ out blockStatement @><- ->"
				<% 
					functionDeclaration.BlockStatement = (BlockStatement)blockStatement;
					functionDeclaration.BlockEndOffset = this.Token.EndOffset;
					functionDeclaration.EndOffset = this.Token.EndOffset;
				%>
			]]></Production>
		</NonTerminal>
		<NonTerminal Key="Identifier" Parameters="out Identifier identifier">
			<Production><![CDATA[
				<%
					identifier = null;
				%>
				'Identifier'
				<% 
					identifier = new Identifier(this.TokenText, this.Token.TextRange); 
				%>
			]]></Production>
		</NonTerminal>
		<NonTerminal Key="FunctionParameterList" Parameters="out AstNodeList parameterList">
			<Production><![CDATA[
				<%
					parameterList = new AstNodeList(null);
					Identifier parameterName;
				%>
				"Identifier<@ out parameterName @><+ parameterList.Add(parameterName); +>"
				{
					'Comma' 
					"Identifier<@ out parameterName @><+ parameterList.Add(parameterName); +><- ->"
				}
			]]></Production>
		</NonTerminal>
		
		<!-- Statements -->
		<NonTerminal Key="Statement" Parameters="out Statement statement">
			<Production><![CDATA[
				<%
					statement = null;
					System.Int32 startOffset = this.LookAheadToken.StartOffset;
				%>
				"Block<@ out statement @>"
				| (
					<%
						// Empty statement
					%>
					'SemiColon'
					<%
						statement = new EmptyStatement(this.Token.TextRange);
					%>
				)
				| (
					<%
						// Variable declaration statement
						Identifier variableName = null;
					%>
					'Var'
					"Identifier<@ out variableName @>"
					'SemiColon<- ->'
					<%
						statement = new VariableDeclarationStatement(variableName, new TextRange(startOffset, this.Token.EndOffset));
					%>
				)
				| (
					<%
						// Assignment statement
						Identifier variableName = null;
						Expression expression = null;
					%>
					"Identifier<@ out variableName @>"
					'Assignment'
					"Expression<@ out expression @>"
					'SemiColon<- ->'
					<%
						statement = new AssignmentStatement(variableName, expression, new TextRange(startOffset, this.Token.EndOffset));
					%>
				)
				| (
					<%
						// Return statement
						Expression expression = null;
					%>
					'Return'
					"Expression<@ out expression @>"
					'SemiColon<- ->'
					<%
						statement = new ReturnStatement(expression, new TextRange(startOffset, this.Token.EndOffset));
					%>
				)
			]]></Production>
		</NonTerminal>
		<NonTerminal Key="Block" Parameters="out Statement block">
			<Production><![CDATA[
				<%
					block = new BlockStatement();
					block.StartOffset = this.LookAheadToken.StartOffset;
					Statement statement;
					System.Int32 statementCurlyBraceLevel = curlyBraceLevel;
				%>
				'OpenCurlyBrace'
				<%
					System.Boolean errorReported = false;
					while (!this.IsAtEnd) {
						if ((this.TokenIs(this.LookAheadToken, SimpleTokenID.CloseCurlyBrace)) && (curlyBraceLevel == statementCurlyBraceLevel + 1))
							break;
						else if (IsNonTerminal("Statement")) {
							errorReported = false;
					%>
							{ "Statement<@ out statement @><+ ((BlockStatement)block).Statements.Add(statement); +><- if (!this.TokenIs(this.LookAheadToken, SimpleTokenID.CloseCurlyBrace)) this.AdvanceToNext(); ->" }
					<%
						}
						else {
							// Error recovery:  Advance to the next token since nothing was matched
							if (!errorReported) {
								this.ReportSyntaxError("Statement expected.");
								errorReported = true;
							}
							this.AdvanceToNext();
						}
					}
				%>
				'CloseCurlyBrace<- ->'
				<%
					block.EndOffset = this.Token.EndOffset;
				%>
			]]></Production>
		</NonTerminal>
		
		<!-- Expressions -->
		<NonTerminal Key="Expression" Parameters="out Expression expression">
			<Production><![CDATA[
				"EqualityExpression<@ out expression @>"
			]]></Production>
		</NonTerminal>
		<NonTerminal Key="EqualityExpression" Parameters="out Expression expression">
			<Production><![CDATA[
				<%
					System.Int32 startOffset = this.LookAheadToken.StartOffset;
					Expression rightExpression;
				%>
				"AdditiveExpression<@ out expression @>"
				{
					<%
						OperatorType operatorType = OperatorType.None;
					%>
					(
						'Equality<+ operatorType = OperatorType.Equality; +>'
						| 'Inequality<+ operatorType = OperatorType.Inequality; +>'
					)
					"EqualityExpression<@ out rightExpression @>"
					<%
						expression = new BinaryExpression(operatorType, expression, rightExpression, new TextRange(startOffset, this.Token.EndOffset));
					%>
				}
			]]></Production>
		</NonTerminal>
		<NonTerminal Key="AdditiveExpression" Parameters="out Expression expression">
			<Production><![CDATA[
				<%
					System.Int32 startOffset = this.LookAheadToken.StartOffset;
					Expression rightExpression;
				%>
				"MultiplicativeExpression<@ out expression @>"
				{
					<%
						OperatorType operatorType = OperatorType.None;
					%>
					(
						'Addition<+ operatorType = OperatorType.Addition; +>'
						| 'Subtraction<+ operatorType = OperatorType.Subtraction; +>'
					)
					"AdditiveExpression<@ out rightExpression @>"
					<%
						expression = new BinaryExpression(operatorType, expression, rightExpression, new TextRange(startOffset, this.Token.EndOffset));
					%>
				}
			]]></Production>
		</NonTerminal>
		<NonTerminal Key="MultiplicativeExpression" Parameters="out Expression expression">
			<Production><![CDATA[
				<%
					System.Int32 startOffset = this.LookAheadToken.StartOffset;
					Expression rightExpression;
				%>
				"PrimaryExpression<@ out expression @>"
				{
					<%
						OperatorType operatorType = OperatorType.None;
					%>
					(
						'Multiplication<+ operatorType = OperatorType.Multiplication; +>'
						| 'Division<+ operatorType = OperatorType.Division; +>'
					)
					"MultiplicativeExpression<@ out rightExpression @>"
					<%
						expression = new BinaryExpression(operatorType, expression, rightExpression, new TextRange(startOffset, this.Token.EndOffset));
					%>
				}
			]]></Production>
		</NonTerminal>
		<NonTerminal Key="PrimaryExpression" Parameters="out Expression expression">
			<Production><![CDATA[
				<%
					expression = null;
					System.Int32 startOffset = this.LookAheadToken.StartOffset;
				%>
				'Number<+ expression = new NumberExpression(Convert.ToInt32(this.TokenText), this.Token.TextRange); +>'
				| (
					'Identifier'
					<%
						// This shows one way to reduce grammar ambiguity
						if (!this.TokenIs(this.LookAheadToken, SimpleTokenID.OpenParenthesis)) {
							// The next token is not an open parenthesis... must be a simple name
							expression = new SimpleName(this.TokenText, this.Token.TextRange); 
							return true;
						}
	
						expression = new FunctionAccessExpression(new Identifier(this.TokenText, this.Token.TextRange));				
						AstNodeList argumentList = null;
					%>
					'OpenParenthesis'
					[ "FunctionArgumentList<@ out argumentList @>" ]
					'CloseParenthesis<- ->'
					<%
						if (argumentList != null)
							((FunctionAccessExpression)expression).Parameters.AddRange(argumentList.ToArray());				
						expression.TextRange = new TextRange(startOffset, this.Token.EndOffset);
					%>
				)
				| (
					'OpenParenthesis'
					"Expression<@ out expression @>"
					'CloseParenthesis'
					<%
						expression = new ParenthesizedExpression(expression, new TextRange(startOffset, this.Token.EndOffset));
					%>					
				)
			]]></Production>
		</NonTerminal>
		<NonTerminal Key="FunctionArgumentList" Parameters="out AstNodeList argumentList">
			<Production><![CDATA[
				<%
					argumentList = new AstNodeList(null);
					Expression argument;
				%>
				"Expression<@ out argument @><+ argumentList.Add(argument); +>"
				{
					'Comma' 
					"Expression<@ out argument @><+ argumentList.Add(argument); +><- ->"
				}
			]]></Production>
		</NonTerminal>
		
	</NonTerminals>
</Grammar>
	